package VWorldGameStudio;

import FCRendering.FCRMaster;
import Function.FCItemLibrary;
import VWorldGameStudio.touzi.FCTouZiProject;
import lombok.Getter;
import lombok.Setter;
import socket.FCRSocketClient;
import socket.FCRSocketServer;
import utils.FCMixUtil;
import Function.FCMutilPlayCache;
import Function.FCMutilPlayPropulsionCache;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Vector;
import java.util.concurrent.CopyOnWriteArrayList;

import static FCRendering.FCRMaster.*;

/**
 * 存档数据属性类
 */
public class FCSave extends Sprite implements FCItemLibrary.ExtraItemCloneImpl {
    private static final long serialVersionUID = 1L;
    //用作机器区分的
    public String HOST_UID = String.valueOf(System.currentTimeMillis()).substring(5);

    private String time;// 存档时间
    @Getter
    @Setter
    private HashMap<String, String> updateunplaceid = new HashMap<>();// 地图中非放置类修改记录,<mapname-x-y,blockid>
    @Getter
    @Setter
    private HashMap<String, String> updateplaceid = new HashMap<>();// 地图中放置类修改记录,<mapname-x-y,blockid>
    @Getter
    @Setter
    private HashMap<String, Boolean> plotisend = new HashMap<>();// 记录事件触发情况

    @Getter
    @Setter
    private HashMap<String, String> caseiteminfo = new HashMap<>();// 记录已被打开的箱子信息

    @Getter
    @Setter
    private HashMap<String, FCTank> tankSaveIos = new HashMap<>();//记录本机获得的坦克的装载配置等


    /**
     * 检测坦克是否被移动和驾驶
     *
     * @return
     */
    public boolean isTankMoveOfID(String id) {
        //TODO 要求，坦克有被上车或者被拖动的时候就要创建一个tankSaveIos存进来！！
        return tankSaveIos.containsKey(id);
    }


    public String getTime() {
        return this.time;
    }

    public void setTime(String ti) {
        time = ti;
    }


    public FCTank findTankSaveIos(String tankId) {
        if (tankId == null) return null;
        if (tankId.equals("null")) return null;
        return tankSaveIos.get(tankId);
    }


    /**
     * 指定乘降
     */
    public void useTankOfPlayerId(FCPlayerInfo playerInfo, String tankid, String tankHostId) {
        if (tankid == null) return;
        if (tankid.equals("null")) return;

        if (playerInfo != null) {
            FCTank tank = tankLib.getTankOfID(tankid, tankHostId);
            if (tank == null) {
                fcv.getMessage().add("找不到坦克! " + tankHostId + ":" + tankid);
                fcv.showMessage();
                return;
            }
            System.out.println("useTankOfPlayerId " + tankid + " " + tankHostId + " " + tank.hashCode());
            if (tank.getBeingTow() > 0) {
                //正在被牵引中，不能进
                fcv.getMessage().add("正在被牵引中，不能进!");
                fcv.showMessage();
                return;
            }

            if (playerInfo.getPlayertank1() == null || playerInfo.getPlayertank1().equals("null")) {// 上车
                if (playerInfo.isDeath()) {
                    fcv.getMessage().add("尸体不可以开车!");
                    fcv.showMessage();
                    return;
                }

                if (tank.getVisable() == 0) {
                    fcv.getMessage().add("不能多人同坐一俩车!");
                    fcv.showMessage();
                    return;
                }
                playerInfo.setPlayertank1(tankid);
                playerInfo.setPlayertankHostId(tankHostId);
                fcv.getMessage().add(playerInfo.getChName() + "上车了 " + langLib.getNameOfId(tankid));
                fcv.showMessage();
                if (tank.getHostId().equals(gameSave.HOST_UID)) {
                    /**
                     * TODO 如果坦克上有道具，则生成clone体 本地的车
                     */
                    tank.setChassisID(checkTankItem(tank.getChassisID()));
                    tank.setEngineID(checkTankItem(tank.getEngineID()));
                    tank.setRadarID(checkTankItem(tank.getRadarID()));
                    tank.setGunID(checkTankItem(tank.getGunID()));
                    tank.setGun2ID(checkTankItem(tank.getGun2ID()));
                    tank.setCdeviceID(checkTankItem(tank.getCdeviceID()));
                    tank.setSEID(checkTankItem(tank.getSEID()));
                    for (int i = 0; i < 10; i++) {
                        FCItem item = itemLib.getItemOfID(tank.getKnapsack()[i]);
                        if (item != null && item.getCatalog().equals("tank")) {
                            tank.getKnapsack()[i] = checkTankItem(tank.getKnapsack()[i]);
                        }
                    }
                    tank.reInitShuxing();
                }

                tank.setVisable(0);
                tank.setPdir(playerInfo.getActionDir());
                tank.setPPianYiX(playerInfo.getPianYiX());
                tank.setPPianYiY(playerInfo.getPianYiY());
                //  if(tank.getPcoorX() == 0 && tank.getPcoorY() == 0) {
                tank.setPcoorX(playerInfo.getPlayer1CoorX());
                tank.setPcoorY(playerInfo.getPlayer1CoorY());
                //  }else {
                //      playerInfo.setPlayer1x(tank.getPcoorX());
                //     playerInfo.setPlayer1y(tank.getPcoorY());
                // }
                tank.setPmapname(playerInfo.getMapname());
                tank.setPactionNum(playerInfo.getActionNum());
                if (tank.getHostId().equals(gameSave.HOST_UID)) {
                    if (!tankSaveIos.containsKey(tankid)) {
                        tankSaveIos.put(tankid, tank);
                        fcv.getLocalPropulsions().add(tank);
                    }
                    if (fcv.isSever()) {
                        FCRSocketServer.getIn().sendTanksSync();
                    } else if (fcv.isClient()) {
                        FCRSocketClient.getIn().sendTanksSync();
                    }
                } else {
                    //TODO 不是本地的车,反控回去,并且请求同步这个车上的所有道具信息过来，
                    if (fcv.isSever()) {
                        FCRSocketServer.getIn().upOrDownYouTank(tankid, tankHostId, true);
                        FCRSocketServer.getIn().getYouTankItemsToMe(tankid, tankHostId);
                    } else if (fcv.isClient()) {
                        FCRSocketClient.getIn().upOrDownYouTank(tankid, tankHostId, true);
                        FCRSocketClient.getIn().getYouTankItemsToMe(tankid, tankHostId);
                    }
                }
                //TODO 本地的用来保存记录的
                FCMutilPlayPropulsionCache.loacalShareIt(tank);
            } else {// 下车
                FCTank find = tankLib.getTankOfID(playerInfo.getPlayertank1(), playerInfo.getPlayertankHostId());
                //TODO 表示自己还坐了一俩车
                if (find != null) {
                    find.setVisable(1);
                    find.setPdir(playerInfo.getActionDir());
                    find.setPPianYiX(playerInfo.getPianYiX());
                    find.setPPianYiY(playerInfo.getPianYiY());
                    find.setPcoorX(playerInfo.getPlayer1CoorX());
                    find.setPcoorY(playerInfo.getPlayer1CoorY());
                    find.setPmapname(playerInfo.getMapname());
                    find.setPactionNum(playerInfo.getActionNum());
                    if (playerInfo.getPlayertankHostId().equals(gameSave.HOST_UID)) {
                        if (fcv.isSever()) {
                            FCRSocketServer.getIn().sendTanksSync();
                        } else if (fcv.isClient()) {
                            FCRSocketClient.getIn().sendTanksSync();
                        }
                    } else {
                        if (fcv.isSever()) {
                            FCRSocketServer.getIn().upOrDownYouTank(tankid, tankHostId, false);
                        } else if (fcv.isClient()) {
                            FCRSocketClient.getIn().upOrDownYouTank(tankid, tankHostId, false);
                        }

                        //下车同步
                        if (FCRMaster.fcv.isSever()) {
                            FCRSocketServer.getIn().syncOthterPlayerTankStateAndItems();
                        } else if (FCRMaster.fcv.isClient()) {
                            FCRSocketClient.getIn().syncOthterPlayerTankStateAndItems();
                        }
                    }
                    FCMutilPlayPropulsionCache.loacalShareIt(find);
                }
                boolean needUpAnotherCar = !tankid.equals(playerInfo.getPlayertank1()) && !tankHostId.equals(playerInfo.getPlayertankHostId());
                if (needUpAnotherCar && tank.getVisable() == 0) {
                    fcv.getMessage().add("不能多人同坐一俩车!");
                    fcv.showMessage();
                    needUpAnotherCar = false;
                }
                fcv.getMessage().add(playerInfo.getChName() + "下车了 " + langLib.getNameOfId(playerInfo.getPlayertank1()));
                fcv.showMessage();
                playerInfo.setPlayertank1("null");
                playerInfo.setPlayertankHostId("null");
                if (needUpAnotherCar) {
                    //还要上车
                    useTankOfPlayerId(playerInfo, tankid, tankHostId);
                } else {
                    boolean canTow = false;
                    if (player1.getPlayertank1() != null && !player1.getPlayertank1().equals("null")) {
                        canTow = true;
                    }
                    if (!canTow) {
                        for (FCRPlayerLink link : FCMutilPlayCache.getTeamMembers()) {
                            FCPlayerInfo p = FCMutilPlayCache.findPlayerByName(link.curPlayerHostUID, link.curPlayerName);
                            if (p != null && p.getPlayertank1() != null && !p.getPlayertank1().equals("null")) {
                                canTow = true;
                                break;
                            }
                        }
                    }
                    if (!canTow) {
                        //不能拖动了
                        player1.removePropulsion();
                        fcv.getMessage().add("没战车在乘，脱勾牵引!");
                        fcv.showMessage();
                    }
                }
            }
        }
        if (fcv.isSever()) {
            FCRSocketServer.getIn().sendPlayerUpDownTank(playerInfo);
        } else if (fcv.isClient()) {
            FCRSocketClient.getIn().sendPlayerUpDownTank(playerInfo);
        }

    }

    public void manualUpdateTankSaveIos() {

    }

    public ArrayList<String> getTankUseTankOfMapTankInfo(HashMap<String, String> maptank) {
        ArrayList<String> ret = new ArrayList<>(0);
        //还要加上队伍中的坦克
        for (String name : fcv.getCanUpTankTeamMembers()) {
            FCPlayerInfo p = FCMutilPlayCache.findPlayerByName(gameSave.HOST_UID, name);
            if (p != null && p.getPlayertank1() != null && !p.getPlayertank1().equals("null")) {
                if (!ret.contains(p.getPlayertank1() + "," + p.getPlayertankHostId())) {
                    ret.add(p.getPlayertank1() + "," + p.getPlayertankHostId());
                }
            }
        }
        //要是已经拿过的坦克就获取,前后多一个格子
        for (FCPropulsion fcPropulsion : fcv.getLocalPropulsions()) {
            if ("tank".equals(fcPropulsion.getPropulsionType())) {
                if (fcPropulsion.getVisable() == 1 && fcPropulsion.getPmapname().equals(FCRMaster.player1.getMapname())
                        && fcPropulsion.getPcoorX() >= FCRMaster.player1.getPlayer1x() - 1
                        && fcPropulsion.getPcoorX() <= FCRMaster.player1.getPlayer1x() + 1
                        && fcPropulsion.getPcoorY() >= FCRMaster.player1.getPlayer1y() - 1
                        && fcPropulsion.getPcoorY() <= FCRMaster.player1.getPlayer1y() + 1) {
                    if (!ret.contains(fcPropulsion.getPropulsionID() + "," + fcPropulsion.getPropulsionHostId())) {
                        ret.add(fcPropulsion.getPropulsionID() + "," + fcPropulsion.getPropulsionHostId());
                    }
                }
            }
        }

        //还要将牵引的也放上去
        for (FCPropulsion propulsion : fcv.getPropulsions()) {
            if (!ret.contains(propulsion.getPropulsionID() + "," + propulsion.getPropulsionHostId())) {
                ret.add(propulsion.getPropulsionID() + "," + propulsion.getPropulsionHostId());
            }
        }

        //判断获取地图原生未获取的坦克
        for (String coor : maptank.keySet()) {
            //coor = x*y  maptank.get(coor) 是坦克id
            FCTank find = findTankSaveIos(maptank.get(coor));
            if (find == null) {
                if (coor.equals(FCRMaster.player1.getPlayer1x() + "*" + FCRMaster.player1.getPlayer1y())) {
                    ret.add(maptank.get(coor) + "," + gameSave.HOST_UID);
                }
            }
        }

        //TODO 必须是没人在用的
        CopyOnWriteArrayList<FCPropulsion> fcPropulsions = FCMutilPlayPropulsionCache.mapToPropulsionMap.get(player1.getMapname());
        if (fcPropulsions != null && !player1.getMapname().equals("home3")) {
            for (FCPropulsion propulsion : fcPropulsions) {
                if (propulsion.getVisable() == 1 && !propulsion.isBeingTow()
                        && propulsion.getPcoorX() >= FCRMaster.player1.getPlayer1x() - 1
                        && propulsion.getPcoorX() <= FCRMaster.player1.getPlayer1x() + 1
                        && propulsion.getPcoorY() >= FCRMaster.player1.getPlayer1y() - 1
                        && propulsion.getPcoorY() <= FCRMaster.player1.getPlayer1y() + 1) {
                    if (!ret.contains(propulsion.getPropulsionID() + "," + propulsion.getPropulsionHostId())) {
                        ret.add(propulsion.getPropulsionID() + "," + propulsion.getPropulsionHostId());
                    }
                }
            }
        }
        return ret;
    }

    public void setCaseUpdateInfo(String id, String item[]) {
        if (caseiteminfo.containsKey(id))
            caseiteminfo.replace(id, item[0] + "," + item[1] + "," + item[2] + "," + item[3]);
        else
            caseiteminfo.put(id, item[0] + "," + item[1] + "," + item[2] + "," + item[3]);
    }


    public HashMap<String, Boolean> getPlotIsEnd() {
        return this.plotisend;
    }

    public void updatePlotIsEndOfId(String id, boolean isend) {
        plotisend.put(id, isend);
    }

    //TODO 有一些boss剧情战斗，已经打过了都要存在这里表示会再触发
    //key:mapName*x*y  地址， val:表示这个npc的名字
    @Getter
    private HashMap<String, FCBossRecord> battleBossMaps = new HashMap<>();

    //TODO 其他的任意事件保存在这里，保存后，地图不会在绘画该事件和触发该事件，和行走阻碍该事件
    //key:mapName*x*y  地址， val:表示这个npc的名字
    @Getter
    private HashMap<String, String> otherEventMaps = new HashMap<>();

    @Getter
    private CopyOnWriteArrayList<String> saveFCPropulsionStrings = new CopyOnWriteArrayList<>();

    //很重要
    public int perV = 12;

    /**
     * 用来保存所有获得的坦克类道具物品
     * Key 是FCItem的hashcode
     */
    @Getter
    public HashMap<String, FCItem> saveAllTankItem = new HashMap<>();

    public void removeLocalItems(ArrayList<String> tmp, FCTank tank) {
        tmp.remove(tank.getGunID());
        tmp.remove(tank.getChassisID());
        tmp.remove(tank.getGun2ID());
        tmp.remove(tank.getSEID());
        tmp.remove(tank.getEngineID());
        tmp.remove(tank.getRadarID());
        tmp.remove(tank.getCdeviceID());
        for (String k : tank.getKnapsack()) {
            if (k != null && k.contains(",")) {
                tmp.remove(k);
            }
        }
    }

    /**
     * 凡是坦克道具的获取都要调用这个来clone对象，存档必要
     *
     * @param
     * @return
     */
    public String checkTankItem(String itemId) {
        if (itemId == null) return null;
        if (itemId.equals("null")) return itemId;
        if (!itemId.contains(",")) {
            FCItem fcItem = itemLib.getItemOfID(itemId);
            if (fcItem != null && fcItem.getCatalog().equals("tank") && !fcItem.getType().equals("plate")
                    && !fcItem.getType().equals("shell") && !fcItem.getType().equals("other")) {
                //不是所有坦克道具都要备份喔，炮弹不用
                fcItem = fcItem.getClone();
                fcItem.initItem();
                itemId = itemId + "," + fcItem.hashCode();
                saveAllTankItem.put(itemId, fcItem);
                System.out.println("生成了副体 " + itemId);
            }
        }
        return itemId;
    }

    public String checkOtherItem(String itemId) {
        if (itemId == null) return null;
        if (itemId.equals("null")) return itemId;
        if (!itemId.contains(",")) {
            FCItem fcItem = itemLib.getItemOfID(itemId);
            if (fcItem != null && fcItem.getType().equals("pants")) {
                fcItem = fcItem.getClone();
                fcItem.initItem();
                itemId = itemId + "," + fcItem.hashCode();
                saveAllTankItem.put(itemId, fcItem);
                System.out.println("生成了副体 " + itemId);
            }
        }
        return itemId;
    }

    /**
     * 当坦克道具被销毁和卖掉后，就要移除掉这个备份体
     *
     * @param itemId
     */
    public void delTankItemClone(String itemId) {
        if (itemId == null) return;
        if (itemId.equals("null")) return;
        if (itemId.contains(",")) {
            saveAllTankItem.remove(itemId);
            System.out.println("删除了副体 " + itemId);
        }
    }

    //TODO 经过了坦克被别的玩家拿走操作了一番可能坦克增加了不少物品
    public void updateOrAddTankItem(String hashName, FCItem item) {
        saveAllTankItem.remove(hashName);
        saveAllTankItem.put(hashName, item);
    }


    @Override
    public FCItem getCloneFcItem(String itemId) {
        return saveAllTankItem.get(itemId);
    }


    @Getter
    private int stepCount = 0;//计步器，角色的计步计算,以主角变了一个格子为一步

    public void addStepCount() {//增加步数
        stepCount++;
    }

    //城镇传送记录已经开通的传送点，key 是地图名称， val是跳转事件Id
    @Getter
    private HashMap<String, String> chuanZhenMaps = new HashMap<>();

    //战车传送记录已经开通的传送点，key 是地图名称， val是跳转事件Id
    @Getter
    private HashMap<String, String> tankChuanZhenMaps = new HashMap<>();

    @Getter
    //发生的eventid需要记录的都记录在这里
    private CopyOnWriteArrayList<String> fcEventHasHanppen = new CopyOnWriteArrayList<>();

    @Getter//杀了什么怪多少次记录
    private HashMap<String, Integer> fcMonsterKillRecordMap = new HashMap<>();

    @Getter //管家银行保管列表,key是物品id
    private CopyOnWriteArrayList<String> fcBankList = new CopyOnWriteArrayList<>();

    @Getter//表示正在租的车的名字
    private ArrayList<String> fcZucheTankList = new ArrayList<>(4);

    @Getter//已经拿了赏金的boss的列表
    private ArrayList<String> hasGetRewardMonsterList = new ArrayList<>();

    @Getter
    //记录地图的扫描宝物被取走key = x+"*"+y+"*"+mapName
    private ArrayList<String> hiddenItemWasTakeList = new ArrayList<>();


    @Getter
    @Setter //遇怪值，越大越难遇怪，可通过迷彩条调高
    private int yuGuaiJilv = 82;

    @Getter
    @Setter //就是这个值一直减，减到0的时候 yuGuaiJilv = 80;
    private int qiXiPingBiSteps = 0;


    @Getter//记录所有已经用钥匙开过了的门
    private ArrayList<String> saveAllHasUnLockDoors = new ArrayList<>();


    @Getter
    @Setter //是否已经开启过了地图功能，要购买卫星地图使用开启
    private boolean hasStartMapFunction = false;


    @Getter//用来记录对话事件的对话序号的，比如把对话1结束了，然后下次对话应该自动选择成对话2了，这样
    private HashMap<String, Integer> sayEventTalkSelects = new HashMap<>();

    @Getter //记录本地的被留在原地的npc队友数据
    private HashMap<String, FCPlayerInfo> outTeamLocalNpcs = new HashMap<>();

    @Getter
    private CopyOnWriteArrayList<FCTouZiProject> touZiProjects = new CopyOnWriteArrayList<>();

    @Getter
    @Setter //是否成立了公司
    private boolean createCompany = false;

    @Getter //自定义的消息
    private HashMap<Integer, String> playerMsgs = new HashMap<>();

    @Getter
    //TODO 举个例子，比如A剧情要一个参数B成立才不会触发，那B参数需要B剧情来写入，就需要下面这个了
    private HashMap<String, String> plotTouchOffKeyMaps = new HashMap<>();

    public String getPlotTouchOffVal(String key){
        String s = plotTouchOffKeyMaps.get(key);
        if(s != null) return s;
        return "-1";
    }

    @Getter//改变npc对话的集合, key是FCCharacter npc名称，val是新的对话id
    private HashMap<String, String> changeNpcSays = new HashMap<>();
}
